﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Design.Serialization;
using System.ComponentModel.Design;
using UIDesigner.FieldHandlers.Bases;
using System.Diagnostics;
using UIDesigner.Designers;
using System.Drawing.Design;
using System.Windows.Forms.Design.Behavior;
using SharedClasses;
using AFSharedLibrary;
using DDW;
using System.IO;
using UIDesigner.FieldHandlers;
using System.Reflection;
using System.Threading;
using UIDesigner.SurfaceProperties.Operations;
using UIDesigner.SurfaceProperties.Information;
using UIDesigner.Editors;
using AFSharedLibrary.SharedControls.Framework;

namespace UIDesigner.SurfaceProperties.Templates
{
    [Serializable()]
    public partial class CreateOptionTemplate : UserControl, ITemplate, ITemplateOptionPanel 
    {
        private Dictionary<string, ConstructedTypeNode> m_rgRequestedTypes;
        private Dictionary<string, CompilationUnitNode> m_rgCompiledFiles;
        private CreateProperties m_objCreateProperties;
        private int m_nIndex;
        private AFDesignerHost m_objHost;
        private Construct m_objConstruct;
        private string m_strObjectName;
        private UIDesigner.LayoutMode m_eLayoutMode = UIDesigner.LayoutMode.TableLayout;
        private string m_strHeader;
        private Dictionary<string, FieldSpecification> m_rgFieldSpecifications = new Dictionary<string, FieldSpecification>();
        private Panel m_ctrlLayoutPanel;
        private bool m_bIsBusObject = false;
        private string m_strObjectType;
        private string m_strObjectNamespace;
        private string m_strPropertyName;
        private string m_strBindingSourceProperty;
        private System.Windows.Forms.Timer m_objHeaderTimer;
        private int m_hOverlayControl;
        private bool m_bCapture;
        private ISelectionService m_objSelectionService;
        private bool m_bFirstPaint;
        private string m_strBusObjectsLocation;
        private bool m_bSelected = false;
        private StatusBar m_ctrlStatusBar;
        private bool m_bReset;
        private bool m_bHasInstantiated;
        private bool m_bUseErrorProvider = true;
        public event UIEventProviderHandlers.CanSaveHandler CanSave;
        public event UIEventProviderHandlers.SaveHandler Save;
        public event UIEventProviderHandlers.CancelHandler Cancel;
        private Control m_ctrlFirstTab;
        private string m_strFirstTabControlName;

        public string FirstTabControlName
        {
            get 
            { 
                return this.FirstTabControl.Name; 
            }
            
            set 
            { 
                m_strFirstTabControlName = value; 
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Control FirstTabControl
        {
            get 
            { 
                return m_ctrlFirstTab; 
            }

            set
            {
                m_ctrlFirstTab = value;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool UseErrorProvider
        {
            get 
            { 
                return m_bUseErrorProvider; 
            }
            
            set 
            { 
                m_bUseErrorProvider = value; 
            }
        }

        public CreateProperties CreateProperties
        {
            set 
            { 
                m_objCreateProperties = value; 
            }
        }

        public int Index
        {
            get
            {
                return m_nIndex;
            }

            set 
            { 
                m_nIndex = value; 
            }
        }

        public AFDesignerHost Host
        {
            set 
            { 
                m_objHost = value; 
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public Construct BusinessObjectConstruct
        {
            get 
            {
                return m_objConstruct;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string BusObjectsLocation
        {
            get
            {
                return m_strBusObjectsLocation;
            }

            set
            {
                m_strBusObjectsLocation = value;
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string ObjectName
        {
            get
            {
                return m_strObjectName;
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string PropertyName
        {
            get 
            { 
                return m_strPropertyName; 
            }
            
            set 
            { 
                m_strPropertyName = value; 
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string BindingSourceProperty
        {
            get
            {
                return m_strBindingSourceProperty;
            }

            set
            {
                m_strBindingSourceProperty = value;
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string ObjectNamespace
        {
            get 
            { 
                return m_strObjectNamespace; 
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string ObjectType
        {
            get 
            { 
                return m_strObjectType; 
            }
        }

        [Category("Object Information"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsBusinessObject
        {
            get 
            { 
                return m_bIsBusObject; 
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                Rebuild();
            }
        }

        [Editor(typeof(FieldSpecEditor), typeof(UITypeEditor))]
        [Category("Behavior"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public Dictionary<string, FieldSpecification> FieldSpecifications
        {
            get 
            { 
                return m_rgFieldSpecifications; 
            }
        }

        [Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string HeaderText
        {
            get 
            { 
                return m_strHeader; 
            }
            
            set 
            { 
                m_strHeader = value;
            }
        }

        [Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public LayoutMode LayoutMode
        {
            get 
            { 
                return m_eLayoutMode; 
            }
            
            set 
            { 
                if (m_eLayoutMode != value)
                {
                    PropertyDescriptorCollection rgProperties = TypeDescriptor.GetProperties(this);
                    PropertyDescriptor objProperty = rgProperties.Find("LayoutMode", false);
                    object objOldValue = m_eLayoutMode;

                    ComponentChangeService.OnComponentChanging(this, objProperty);

                    m_eLayoutMode = value;

                    ComponentChangeService.OnComponentChanged(this, objProperty, objOldValue, m_eLayoutMode);
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Construct Construct
        {
            set 
            { 
                m_objConstruct = value;
                m_strObjectName = m_objConstruct.Name;
                m_strHeader = m_objConstruct.Name; 
            }

            get
            {
                return m_objConstruct;
            }
        }

        public void RemoveControls()
        {
            RemoveControls(this);
        }

        public void RemoveControls(Control ctrlParent)
        {
            IContainer objContainer = (IContainer)m_objHost;

            foreach (Control ctrlControl in ctrlParent.Controls)
            {
                RemoveControls(ctrlControl);

                ((IContainer)m_objHost).Remove(ctrlControl);

                ctrlControl.Dispose();
            }

            objContainer.Remove(ctrlParent);
            ctrlParent.Dispose();
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            this.components = new System.ComponentModel.Container();

            m_objHeaderTimer = new System.Windows.Forms.Timer(this.components);

            m_objHeaderTimer.Interval = 100;
            m_objHeaderTimer.Enabled = false;
            m_objHeaderTimer.Tick += new EventHandler(HeaderTimerTick);

            if (!m_bReset)
            {
                Rebuild();
            }
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
        }

        private void HeaderTimerTick(object sender, EventArgs e)
        {
            ISelectionService objSvc = (ISelectionService)((IServiceContainer)m_objHost).GetService(typeof(ISelectionService));

            if (objSvc.SelectionCount == 1)
            {
                object[] rgComponents = (object[])m_objSelectionService.GetSelectedComponents();
                IComponent objIComponent = (IComponent)rgComponents[0];

                if (objIComponent == this)
                {
                    m_objHeaderTimer.Stop(); 
                }
                else
                {
                    objSvc.SetSelectedComponents(new IComponent[1] { this });
                }
            }
            else
            {
                m_objHeaderTimer.Stop();
                objSvc.SetSelectedComponents(new IComponent[1] { this });
            }
        }

        protected IComponentChangeService ComponentChangeService
        {
            get
            {
                return (IComponentChangeService) m_objHost;
            }
        }

        protected bool TypeIsBusObject(ConstructedTypeNode objConstruct)
        {
            ClassNode objClass = objConstruct as ClassNode;
            
            if (objClass == null)
            {
                if (objConstruct.Name.Identifier == typeof(IBusinessObject).Name)
                {
                    return true;
                }
            }

            foreach (TypeNode objTypeNode in objClass.BaseClasses)
            {
                RequestType(objTypeNode.Identifier.GenericIdentifier, out objConstruct);

                if (objConstruct != null && TypeIsBusObject(objConstruct))
                {
                    return true;
                }
            }

            return false;
        }


        protected void RequestType(DirectoryInfo objDir, string strName, out ConstructedTypeNode objTypeNodeOut)
        {
            Type objType = Type.GetType("System." + strName, false, true);

            objTypeNodeOut = null;

            if (objType != null)
            {
                return;
            }

            if (m_rgRequestedTypes == null)
            {
                m_rgRequestedTypes = new Dictionary<string, ConstructedTypeNode>();
            }
            else
            {
                if (m_rgRequestedTypes.ContainsKey(strName))
                {
                    objTypeNodeOut = m_rgRequestedTypes[strName];
                    return;
                }
            }

            foreach (FileInfo objFile in objDir.GetFiles())
            {
                if (objFile.Name.EndsWith(".cs"))
                {
                    CompilationUnitNode objNode;

                    if (m_rgCompiledFiles == null)
                    {
                        m_rgCompiledFiles = new Dictionary<string, CompilationUnitNode>();
                        objNode = CSharpParser.Parse(objFile.FullName);

                        m_rgCompiledFiles.Add(objFile.FullName, objNode);
                    }
                    else
                    {
                        if (m_rgCompiledFiles.ContainsKey(objFile.FullName))
                        {
                            objNode = m_rgCompiledFiles[objFile.FullName];
                        }
                        else
                        {
                            objNode = CSharpParser.Parse(objFile.FullName);
                            m_rgCompiledFiles.Add(objFile.FullName, objNode);
                        }
                    }

                    foreach (NamespaceNode objNamespace in objNode.Namespaces)
                    {
                        foreach (ClassNode objClass in objNamespace.Classes)
                        {
                            if (objClass.Name.Identifier == strName)
                            {
                                objTypeNodeOut = objClass;
                                return;
                            }
                        }

                        foreach (StructNode objStruct in objNamespace.Structs)
                        {
                            if (objStruct.Name.Identifier == strName)
                            {
                                objTypeNodeOut = objStruct;
                                return;
                            }
                        }

                        foreach (InterfaceNode objInterface in objNamespace.Interfaces)
                        {
                            if (objInterface.Name.Identifier == strName)
                            {
                                objTypeNodeOut = objInterface;
                                return;
                            }
                        }

                        foreach (EnumNode objEnum in objNamespace.Enums)
                        {
                            if (objEnum.Name.Identifier == strName)
                            {
                                objTypeNodeOut = objEnum;
                                return;
                            }
                        }
                    }

                    foreach (ClassNode objClass in objNode.DefaultNamespace.Classes)
                    {
                        if (objClass.Name.Identifier == strName)
                        {
                            objTypeNodeOut = objClass;
                            return;
                        }
                    }

                    foreach (StructNode objStruct in objNode.DefaultNamespace.Structs)
                    {
                        if (objStruct.Name.Identifier == strName)
                        {
                            objTypeNodeOut = objStruct;
                            return;
                        }
                    }

                    foreach (InterfaceNode objInterface in objNode.DefaultNamespace.Interfaces)
                    {
                        if (objInterface.Name.Identifier == strName)
                        {
                            objTypeNodeOut = objInterface;
                            return;
                        }
                    }

                    foreach (EnumNode objEnum in objNode.DefaultNamespace.Enums)
                    {
                        if (objEnum.Name.Identifier == strName)
                        {
                            objTypeNodeOut = objEnum;
                            return;
                        }
                    }
                }
            }

            foreach (DirectoryInfo objSubDir in objDir.GetDirectories())
            {
                RequestType(objSubDir, strName, out objTypeNodeOut);

                if (objTypeNodeOut != null)
                {
                    return;
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        protected IServiceContainer ServiceContainer
        {
            get
            {
                return (IServiceContainer)m_objHost;
            }
        }

        protected void RequestType(string strName, out ConstructedTypeNode objTypeNodeOut)
        {
            DirectoryInfo objDir = new DirectoryInfo(m_strBusObjectsLocation);

            RequestType(objDir, strName, out objTypeNodeOut);
        }

        protected void OnPaint(object sender, PaintEventArgs e)
        {
            if (!m_bFirstPaint)
            {
                if (this.Site != null)
                {
                    m_objHost = (AFDesignerHost)this.Site.Container;
                    m_objSelectionService = (ISelectionService)this.ServiceContainer.GetService(typeof(ISelectionService));

                    m_objSelectionService.SelectionChanged += new EventHandler(SelectionChanged);
                }

                m_bFirstPaint = true;
            }
        }

        protected void SelectionChanged(object sender, EventArgs e)
        {
            m_bSelected = false;

            foreach (IComponent objComponent in m_objSelectionService.GetSelectedComponents())
            {
                if (objComponent == this)
                {
                    m_bSelected = true;
                }
            }

            this.Refresh();
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        protected bool IsBrowsable(MemberNode objProperty)
        {
            foreach (AttributeNode objAttr in objProperty.Attributes)
            {
                if (objAttr.Name.GenericIdentifier == "Browsable")
                {
                    BooleanPrimitive objBool = (BooleanPrimitive)objAttr.Arguments[0].Expression;

                    if (objBool.Value == false)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        protected bool IsBusObjectMember(MemberNode objProperty)
        {
            Type objType = typeof(IBusinessObject);

            foreach (MemberInfo objMember in objType.GetMembers())
            {
                string strName = objMember.Name;

                if (strName.StartsWith("get_"))
                {
                    strName = strName.Substring("get_".Length);
                }
                else if (strName.StartsWith("set_"))
                {
                    strName = strName.Substring("set_".Length);
                }

                if (strName == objProperty.Names[0].GenericIdentifier)
                {
                    return true;
                }
            }

            return false;
        }

        private void Rebuild()
        {
            ClassNode objClassNode;
            InterfaceNode objInterfaceNode;
            ConstructedTypeNode objConstructedType = null;
            frmProgress frmProgress = new frmProgress();
            int x;
            int nCount;

            frmProgress.Show();
            frmProgress.Location = this.Parent.PointToScreen(this.Location);

            Application.DoEvents();

            Cursor.Current = Cursors.WaitCursor;

            this.Controls.Clear();

            if (this.LayoutMode == LayoutMode.TableLayout)
            {
                m_ctrlLayoutPanel = (TableLayoutPanel)m_objHost.CreateComponent(typeof(TableLayoutPanel));
            }
            else
            {
                m_ctrlLayoutPanel = (FlowLayoutPanel)m_objHost.CreateComponent(typeof(FlowLayoutPanel));
            }

            m_ctrlLayoutPanel.Dock = DockStyle.Fill;

            this.Controls.Add(m_ctrlLayoutPanel);

            BaseFieldHandler.RequestType += new Handlers.RequestTypeHandler(RequestType);
            BaseFieldHandler.RequestType += new Handlers.RequestTypeHandler(RequestType);

            objClassNode = m_objConstruct.Node as ClassNode;

            if (objClassNode != null)
            {
                m_bIsBusObject = TypeIsBusObject(objClassNode);
                m_strObjectType = objClassNode.Name.Identifier;
                m_strObjectNamespace = m_objConstruct.Namespace;
                m_strPropertyName = m_strObjectType;
                m_strBindingSourceProperty = m_strPropertyName + "BindingSource";
                objConstructedType = objClassNode;
            }
            else
            {
                objInterfaceNode = m_objConstruct.Node as InterfaceNode;

                if (objInterfaceNode != null)
                {
                    m_bIsBusObject = TypeIsBusObject(objInterfaceNode);
                    m_strObjectType = objInterfaceNode.Name.Identifier;
                    m_strObjectNamespace = m_objConstruct.Namespace;
                    m_strPropertyName = m_strObjectType;
                    m_strBindingSourceProperty = m_strPropertyName + "BindingSource";
                    objConstructedType = objInterfaceNode;
                }
            }

            nCount = this.ConstructorInfo.ParmInfos.Count;
            x = 1;

            foreach (SurfaceParmInfo objParmInfo in this.ConstructorInfo.ParmInfos)
            {
                ParmItem objParmItem = objParmInfo.ParmItem;
                ParamDeclNode objParm = objParmItem.Parm;

                if (IsBrowsable(objParmInfo.ParmItem.MatchingProperty))
                {
                    SortedDictionary<float, IFieldHandler> rgHandlers = BaseFieldHandler.FindHandlers(this, objParmItem, m_objHost);
                    FieldSpecification objSpec;

                    frmProgress.Info = "Adding default controls for \"" + objParm.Name + "\"";
                    frmProgress.Progress = (int)(((float)x) / ((float)nCount)) * 80;

                    StatusBar.Text = frmProgress.Info;
                    Application.DoEvents();
#if DEBUG
                    if (m_strObjectNamespace == "AFSharedLibrary")
                    {
                        rgHandlers = new SortedDictionary<float, IFieldHandler>();
                        rgHandlers.Add(0, (IFieldHandler)new MetaDataAttributeHandler(m_objHost));
                    }
                    else
                    {
                        rgHandlers = BaseFieldHandler.FindHandlers(this, objParmItem, m_objHost);
                    }
#else
                    rgHandlers = BaseFieldHandler.FindHandlers(this, objProperty, m_objHost);
#endif

                    if (rgHandlers.Count > 0)
                    {
                        objSpec = new FieldSpecification(this, objConstructedType, objParmItem, rgHandlers);

                        m_rgFieldSpecifications.Add(objSpec.MemberName, objSpec);
                    }
                }

                x++;
            }


            frmProgress.Info = "Adding controls to canvas";
            frmProgress.Progress = 90;

            AddControls();

            frmProgress.Info = "Complete!";
            frmProgress.Progress = 100;

            for (float f = 1; f > 0; f -= .05f)
            {
                frmProgress.Opacity = f;
                Application.DoEvents();
                Thread.Sleep(5);
            }

            frmProgress.Close();

            StatusBar.Text = "Ready";
            Cursor.Current = Cursors.Default;
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        private SurfaceConstructorInfo ConstructorInfo
        {
            get
            {
                return m_objCreateProperties.ConstructorInfos[m_nIndex - 1];
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public StatusBar StatusBar
        {
            get
            {
                return m_ctrlStatusBar;
            }

            set
            {
                m_ctrlStatusBar = value;
            }
        }

        public void AddBindings(string strBindingSourceProperty)
        {
            foreach (FieldSpecification objSpec in m_rgFieldSpecifications.Values)
            {
                if (objSpec.SelectedOption != null)
                {
                    IFieldHandler objHandler = objSpec.SelectedOption.FieldHandler;
                    string strOption = objSpec.SelectedOption.OptionName;

                    objHandler.AddBindings(strOption, objSpec.BoundControl, objSpec.Member, strBindingSourceProperty);
                }
            }
        }

        public CreateOptionTemplate()
        {

        }

        public CreateOptionTemplate(AFDesignerHost objHost, CreateProperties objCreateProperties, int nIndex)
        {
            m_objCreateProperties = objCreateProperties;
            m_nIndex = nIndex;
            m_objHost = objHost;

            this.AutoScroll = true;

            m_strHeader = "Create New " + m_objCreateProperties.ObjectName + " Option #" + m_nIndex.ToString();

            InitializeComponent();

            this.Name = this.TemplateName;
        }

        protected int GetPaddingWidth(TableLayoutPanel ctrlInnerPanel)
        {
            int nWidth = ctrlInnerPanel.Margin.Left + ctrlInnerPanel.Margin.Right;

            nWidth += ctrlInnerPanel.Padding.Left + ctrlInnerPanel.Padding.Right;

            foreach (Control ctrl in ctrlInnerPanel.Controls)
            {
                nWidth += ctrl.Margin.Left + ctrl.Margin.Right;
                nWidth += ctrl.Padding.Left + ctrl.Padding.Right;
            }

            return nWidth;
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string TemplateName
        {
            get 
            {
                return "CreateOption" + m_nIndex.ToString() + "Template";
            }
        }

        public void Reset()
        {
            m_bReset = true;
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasInstantiated
        {
            get
            {
                return m_bHasInstantiated;
            }
        }

        public void InstantiateIn(Control container, Point location)
        {
            m_bHasInstantiated = true;
            this.Location = location;

            container.Controls.Add(this);
        }

        protected int GetPaddingHeight(TableLayoutPanel ctrlInnerPanel)
        {
            int nHeight = ctrlInnerPanel.Margin.Top + ctrlInnerPanel.Margin.Bottom;

            nHeight += ctrlInnerPanel.Padding.Top + ctrlInnerPanel.Padding.Bottom;

            foreach (Control ctrl in ctrlInnerPanel.Controls)
            {
                nHeight += ctrl.Margin.Top + ctrl.Margin.Bottom;

                if (ctrlInnerPanel.RowCount == 1)
                {
                    break;
                }
            }

            return nHeight;
        }

        private void AddControls()
        {
            LayoutManager objLayoutManager;

            if (m_eLayoutMode == LayoutMode.TableLayout)
            {
                LayoutStyle eLayoutStyle;
                int nHighAlignment = 0;
                List<char> rgMnemonics = new List<char>();
                LayoutItem objLayoutItem;
                int nTabIndex = 0;
                int nWidth = 0;
                int nHeight = 0;
                TableLayoutPanel ctrlLayoutPanel = (TableLayoutPanel)m_ctrlLayoutPanel;

                objLayoutManager = new LayoutManager(ctrlLayoutPanel, m_objHost);

                foreach (FieldSpecification objSpec in m_rgFieldSpecifications.Values)
                {
                    if (objSpec.SelectedOption != null)
                    {
                        IFieldHandler objHandler = objSpec.SelectedOption.FieldHandler;
                        string strOption = objSpec.SelectedOption.OptionName;
                        int nAlignment;
                        Size szControl;

                        objHandler.NegotiateLayout(strOption, ctrlLayoutPanel, objSpec.Parm, LayoutMode.TableLayout, ref nTabIndex, out eLayoutStyle, out nAlignment, out szControl);

                        Debug.Assert(eLayoutStyle != LayoutStyle.Unassigned);
                        Debug.Assert(nAlignment != -1);

                        objSpec.TabIndex = nTabIndex - 1;
                        objSpec.LayoutStyle = eLayoutStyle;
                        objSpec.ControlSize = szControl;

                        if (eLayoutStyle == LayoutStyle.HorizontalDoubleCellAligned)
                        {
                            if (nAlignment > nHighAlignment)
                            {
                                nHighAlignment = nAlignment;
                            }
                        }
                    }
                }

                foreach (FieldSpecification objSpec in m_rgFieldSpecifications.Values)
                {
                    if (objSpec.SelectedOption != null)
                    {
                        IFieldHandler objHandler = objSpec.SelectedOption.FieldHandler;
                        string strOption = objSpec.SelectedOption.OptionName;
                        TableLayoutPanel ctrlInnerPanel;
                        Size sz = objSpec.ControlSize;

                        if (objSpec.ControlSize == Size.Empty)
                        {
                            objLayoutItem = objLayoutManager.AddRow(objSpec.LayoutStyle, nHighAlignment, true);
                        }
                        else
                        {
                            if (m_bUseErrorProvider)
                            {
                                ErrorProvider objErrorProvider = new ErrorProvider();

                                objSpec.ControlSize = new Size(objSpec.ControlSize.Width + objErrorProvider.Icon.Width + 2, objSpec.ControlSize.Height);
                            }

                            objLayoutItem = objLayoutManager.AddRow(objSpec.LayoutStyle, nHighAlignment, true, objSpec.ControlSize);
                        }

                        ctrlInnerPanel = objLayoutItem.InnerPanel;
                        objSpec.BoundControl = objHandler.AddDefaultControls(ctrlInnerPanel, objSpec.Parm, objSpec.TabIndex, objLayoutItem.TableLayoutPanelCellPositions, rgMnemonics);
                        objSpec.BoundControl.Size = sz;

                        if (objSpec.TabIndex == 0)
                        {
                            m_ctrlFirstTab = objSpec.BoundControl;
                        }

                        foreach (Control ctrl in ctrlInnerPanel.Controls)
                        {
                            TableLayoutPanelCellPosition objPos = ctrlInnerPanel.GetPositionFromControl(ctrl);
                            ctrl.Tag = objPos.ToString();
                        }
                    }
                }

                foreach (TableLayoutPanel ctrlRow in ctrlLayoutPanel.Controls)
                {
                    if (ctrlRow.Width > nWidth)
                    {
                        nWidth = ctrlRow.Width + GetPaddingWidth(ctrlRow);
                    }

                    nHeight += ctrlRow.Height + GetPaddingHeight(ctrlRow);
                }

                this.Width = nWidth;
                this.Height = nHeight;
            }

            AddBindings();
        }

        public void AddBindings()
        {
            foreach (FieldSpecification objSpec in m_rgFieldSpecifications.Values)
            {
                if (objSpec.SelectedOption != null)
                {
                    IFieldHandler objHandler = objSpec.SelectedOption.FieldHandler;
                    string strOption = objSpec.SelectedOption.OptionName;

                    objHandler.AddBindings(strOption, objSpec.BoundControl, objSpec.Member, this.BindingSourceProperty);
                }
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IBusinessObject BusinessObject
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public BindingSource BindingSource
        {
            get { throw new NotImplementedException(); }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TemplatePanelRole Role
        {
            get 
            {
                return TemplatePanelRole.Option; 
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string LabelText
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        #region ITemplatePanel Members


        public string DebugOutput
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }
}
